[iOS] UIProgressViewのprogressに0.0以下、1.0以上の値を指定した時の挙動
はじめに
こんにちは。モバイルアプリサービス部の加藤潤です。
今回はUIProgressView
のprogress
に0.0
以下、1.0
以上の値を設定した時の挙動を調べてみました。
開発環境
- Xcode 7.3.1 (7D1014)
- iPhone 6s シミュレータ / iOS 9.3 (13E230)
- Swift 2.2
UIProgressViewとは
本題に入る前にごく簡単にUIProgressView
の説明をしておきます。
UIProgressView
はファイルのダウンロードなど、作業の進捗状況を表す際に使用されるUIコンポーネントです。
スタイルがUIProgressViewStyle.Default
だとこんなの。
UIProgressViewStyle.Bar
だとこんなのです。
進捗値の指定について
さて、ここからが本題です。
UIProgressView
の進捗値はprogress
プロパティに値を指定するか、public func setProgress(progress: Float, animated: Bool)
関数で指定します。関数の方は進捗値とあわせてアニメーションの有無も指定することが可能です。
※iOS 9からはobservedProgress
も使用可能ですが、本記事では扱いません。
この進捗値ですが、クラスリファレンスには以下のように書かれています。
The current progress is represented by a floating-point value between 0.0 and 1.0, inclusive, where 1.0 indicates the completion of the task. The default value is 0.0. Values less than 0.0 and greater than 1.0 are pinned to those limits.
値の範囲としては0.0
〜1.0
のようですが、範囲外の値を指定した時の挙動がどうなるのか気になったので調べてみました。
1.0以上の進捗値を指定した場合
まずは1.0
以上のprogress
を指定した場合の挙動を確認してみます。
確認用に以下のようなアプリを用意しました。
setProgress
関数を各ボタンに書かれた進捗値でそれぞれアニメーションのありなしのパターンで呼び出すことができるようにしました。
ソースコードは以下のようになっています。
import UIKit class ViewController: UIViewController { /// プログレスビュー @IBOutlet weak var progressView: UIProgressView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. reset() } // MARK: - アニメーションなし @IBAction func didTapNonAnimated1_0Button(sender: AnyObject) { // 1.0 setProgress(1.0, animated: false) } @IBAction func didTapNonAnimated5_0Button(sender: AnyObject) { // 5.0 setProgress(5.0, animated: false) } @IBAction func didTapNonAnimated10_0Button(sender: AnyObject) { // 10.0 setProgress(10.0, animated: false) } // MARK: - アニメーションあり @IBAction func didTapAnimated1_0Button(sender: AnyObject) { // 1.0 setProgress(1.0, animated: true) } @IBAction func didTapAnimated5_0Button(sender: AnyObject) { // 5.0 setProgress(5.0, animated: true) } @IBAction func didTapAnimated10_0Button(sender: AnyObject) { // 10.0 setProgress(10.0, animated: true) } @IBAction func didTapResetButton(sender: AnyObject) { reset() } // MARK: - Private private func reset() { progressView.progress = 0.0 } private func setProgress(progress: Float, animated: Bool) { CATransaction.setCompletionBlock { NSLog("finish animation") } progressView.setProgress(progress, animated: animated) NSLog("begin animation") } }
setProgress
のアニメーションの時間を計測するためにCATransaction
のsetCompletionBlock
を実行しています。
実行結果(1.0以上の進捗値)
このアプリを動かしてみた結果がこちらです。
見てわかる通り、アニメーションがない場合は1.0
, 5.0
, 10.0
全て一瞬で進捗率が100%となります。
アニメーションしないのだから当然の動きです。
対してアニメーションがある場合は1.0
, 5.0
, 10.0
の全てが最終的には進捗率100%となりますが、アニメーションの時間が異なります。
1.0
の場合はおよそ1秒、5.0
の場合はおよそ5秒、10.0
の場合はおよそ10秒となっています。
このことが何を意味するか...つまり極端に大きい数をprogress
に指定してしまうと、アニメーションの時間が長くなるので、見た目にはプログレスバーの進捗がほとんど進まなくなってしまうということです。
0.0以下の進捗値を指定した場合
次に0.0
以下のprogress
を指定した場合の挙動も確認してみます。
以下のようなアプリを用意しました。
ソースコードは以下のようになっています。
import UIKit class ViewController: UIViewController { /// プログレスビュー @IBOutlet weak var progressView: UIProgressView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. reset() } // MARK: - アニメーションなし @IBAction func didTapNonAnimated0_0Button(sender: AnyObject) { // 0.0 setProgress(0.0, animated: false) } @IBAction func didTapNonAnimatedMinus5_0Button(sender: AnyObject) { // -5.0 setProgress(-5.0, animated: false) } @IBAction func didTapNonAnimatedMinus10_0Button(sender: AnyObject) { // -10.0 setProgress(-10.0, animated: false) } // MARK: - アニメーションあり @IBAction func didTapAnimated0_0Button(sender: AnyObject) { // 0.0 setProgress(0.0, animated: true) } @IBAction func didTapAnimatedMinus5_0Button(sender: AnyObject) { // -5.0 setProgress(-5.0, animated: true) } @IBAction func didTapAnimatedMinus10_0Button(sender: AnyObject) { // -10.0 setProgress(-10.0, animated: true) } @IBAction func didTapResetButton(sender: AnyObject) { reset() } // MARK: - Private private func reset() { progressView.progress = 1.0 } private func setProgress(progress: Float, animated: Bool) { CATransaction.setCompletionBlock { NSLog("finish animation") } progressView.setProgress(progress, animated: animated) NSLog("begin animation") } }
実行結果(0.0以下の進捗値)
このアプリを動かしてみた結果がこちらです。
アニメーションがない場合は0.0
, -5.0
, -10.0
全て一瞬で進捗率が0%となります。
対してアニメーションがある場合は0.0
, -5.0
, -10.0
の全てが最終的には進捗率0%となりますが、やはりアニメーションの時間が異なります。
0.0
の場合はおよそ1(1 - 0.0)
秒、-5.0
の場合はおよそ6(1 - (-5.0))
秒、-10.0
の場合はおよそ11(1 - (-10.0))
秒となっています。
つまりこちらについても極端に小さい数をprogress
に指定してしまうと、アニメーションの時間が長くなるので、見た目にはプログレスバーの進捗がほとんど進まなくなってしまいます。
まとめ
今回調査した内容をまとめると以下になります。
1.0
を超える極端に大きい数をUIProgressView
のprogress
に指定してしまうと、アニメーションする場合にプログレスバーの進捗がほとんど進まなくなってしまう0.0
未満の極端に小さい数をUIProgressView
のprogress
に指定してしまうと、アニメーションする場合にプログレスバーの進捗がほとんど進まなくなってしまうUIProgressView
は進捗値とは別にアニメーションの時間を指定するようなことはできないが、progress
の値を調整することで間接的にアニメーションの時間を調整できる。ただし、上記のようなことが起こるため、極端に大きい数、小さい数を指定しないようにする必要がある。- アニメーションの時間に特にこだわりがない場合はドキュメントに書いてある通り、
0.0
〜1.0
の範囲の値を指定するようにしましょう。